home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
- Amsterdam, The Netherlands.
-
- All Rights Reserved
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the names of Stichting Mathematisch
- Centrum or CWI not be used in advertising or publicity pertaining to
- distribution of the software without specific, written prior permission.
-
- STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
- THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
- FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ******************************************************************/
-
- #include "Python.h"
- #include "import.h"
- #include "pbm.h"
-
- /* The image formats we support */
- static PyObject *format_pbm, *format_choices;
- extern PyObject *getimgformat(); /* Get format by name */
-
- /*
- ** Since PBMPLUS error handling is abysmal (print message, exit),
- ** there is a modified version that has (slightly) better error
- ** handling. Contact jack@cwi.nl if you want it. Define PBMNEWERROR
- ** if you have the modified pbmplus.
- **
- ** If you don't have it the first pbm error will abort you python
- ** program.
- */
- #define PBMNEWERROR
-
- #ifndef PBMNEWERROR
- #define PBM_END
- #define PBM_START if (0) {
- #define PBM_ENDSTART }
-
- #else
-
- #include <setjmp.h>
- jmp_buf pbmerrenv;
- char pbmerrstr[1000];
-
- #define PBM_END pm_setmsghandler(0); pm_setexithandler(0);
- #define PBM_START if ( setjmp(pbmerrenv) != 0 ) { \
- PyErr_SetString(errobject, pbmerrstr); \
- *pbmerrstr = '\0'; \
- PBM_END
- #define PBM_ENDSTART return 0; \
- } \
- pm_setmsghandler(my_pmerr); \
- pm_setexithandler(my_pmexit);
-
-
- static void
- my_pmerr(str)
- char *str;
- {
- strncpy(pbmerrstr, str, 999);
- }
-
- static void
- my_pmexit()
- {
- longjmp(pbmerrenv, 1);
- }
-
- #endif /* PBMNEWERROR */
-
- /* Pbm objects */
-
- typedef struct {
- PyObject_HEAD
- PyObject *dict; /* Attributes dictionary */
- int is_reader; /* TRUE if this is a reader */
- char *filename; /* filename of the image file */
- FILE *filep;
- int format;
- } pbmobject;
-
- static PyObject *errobject;
-
- staticforward PyTypeObject Pbmtype;
-
- #define is_pbmobject(v) ((v)->ob_type == &Pbmtype)
-
- static char doc_pbm[] = "This object reads/writes PBM files\n"
- "The 'width', 'height' and 'format' attributes describe the picture\n"
- "For writers, setting 'forceplain' creates an ASCII PBM file.";
-
- /* Routine to easily obtain C data from the dict python data */
- int
- pbmselfattr(self, name, fmt, ptr, wanterr)
- pbmobject *self;
- char *name;
- char *fmt;
- void *ptr;
- int wanterr;
- {
- PyObject *obj;
- char errbuf[100];
-
- obj = PyDict_GetItemString(self->dict, name);
- if ( obj == NULL ) {
- if ( wanterr ) {
- sprintf(errbuf, "Required attribute '%s' not set", name);
- PyErr_SetString(errobject, errbuf);
- return 0;
- } else {
- PyErr_Clear();
- return 0;
- }
- }
- if ( !PyArg_Parse(obj, fmt, ptr) ) {
- if ( !wanterr )
- PyErr_Clear();
- return 0;
- }
- return 1;
- }
-
- /* Routine to easily insert integer into dictionary */
- pbmsetintattr(self, name, value)
- pbmobject *self;
- char *name;
- int value;
- {
- PyObject *obj;
- int rv;
-
- obj = PyInt_FromLong(value);
- rv = PyDict_SetItemString(self->dict, name, obj);
- Py_DECREF(obj);
- return rv;
- }
-
- static pbmobject *
- newpbmobject()
- {
- pbmobject *xp;
- xp = PyObject_NEW(pbmobject, &Pbmtype);
- if (xp == NULL)
- return NULL;
- xp->dict = PyDict_New();
- xp->filename = NULL;
- xp->filep = NULL;
- return xp;
- }
-
- static int
- initpbmreader(self, name)
- pbmobject *self;
- char *name;
- {
- char *name_copy;
- int cols, rows;
-
- if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
- PyErr_NoMemory();
- return 0;
- }
- strcpy(name_copy, name);
- self->filename = name_copy;
- self->is_reader = 1;
-
- if ((self->filep = fopen(self->filename, "rb")) == NULL ) {
- PyErr_SetFromErrno(PyExc_IOError);
- return 0;
- }
- PBM_START
- fclose(self->filep);
- self->filep = 0;
- return 0;
- PBM_ENDSTART
- pbm_readpbminit(self->filep, &cols, &rows, &self->format);
- PBM_END
-
- pbmsetintattr(self, "width", cols);
- pbmsetintattr(self, "height", rows);
- PyDict_SetItemString(self->dict, "format", format_pbm);
- PyDict_SetItemString(self->dict, "format_choices", format_choices);
- if ( PyErr_Occurred() )
- return 0;
- return 1;
- }
-
- static int
- initpbmwriter(self, name)
- pbmobject *self;
- char *name;
- {
- char *name_copy;
-
- if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
- PyErr_NoMemory();
- return 0;
- }
- strcpy(name_copy, name);
- self->filename = name_copy;
- self->filep = NULL;
- self->is_reader = 0;
- PyDict_SetItemString(self->dict, "format", format_pbm);
- PyDict_SetItemString(self->dict, "format_choices", format_choices);
- if( PyErr_Occurred())
- return 0;
- return 1;
- }
-
- /* Pbm methods */
-
- static void
- pbm_dealloc(xp)
- pbmobject *xp;
- {
- Py_XDECREF(xp->dict);
- if( xp->filename )
- free(xp->filename);
- if( xp->filep )
- fclose(xp->filep);
- PyMem_DEL(xp);
- }
-
- static char doc_read[] = "Read the actual data, returns a string";
-
- static PyObject *
- pbm_read(self, args)
- pbmobject *self;
- PyObject *args;
- {
- int i, w, h, rowlen;
- PyObject *rv;
- char *datap;
- bit *pixelrow;
- PyObject *fmt;
-
- if (!PyArg_ParseTuple(args,""))
- return NULL;
- if (!self->is_reader) {
- PyErr_SetString(errobject, "Cannot read() from writer object");
- return NULL;
- }
- /* XXXX Read data and return it */
- /* XXXX Get args from self->dict and write the data */
- if ( !pbmselfattr(self, "width", "i", &w, 1) ||
- !pbmselfattr(self, "height", "i", &h, 1) ||
- !pbmselfattr(self, "format", "O", &fmt, 1) )
- return NULL;
- if ( fmt != format_pbm ) {
- PyErr_SetString(errobject, "Unsupported image format");
- return NULL;
- }
- pixelrow = 0;
- rv = 0;
- PBM_START
- if ( pixelrow )
- pbm_freerow(pixelrow);
- if ( rv )
- Py_DECREF(rv);
- return NULL;
- PBM_ENDSTART
-
- rowlen = w;
- pixelrow=pbm_allocrow(w);
-
- if ( (rv=PyString_FromStringAndSize(0, rowlen*h)) == NULL ) {
- pbm_freerow(pixelrow);
- return NULL;
- }
- datap = PyString_AsString(rv);
-
- while( h > 0 ) {
- pbm_readpbmrow(self->filep, pixelrow, w, self->format);
- for(i=0; i<w; i++)
- datap[i] = pixelrow[i];
- datap += rowlen;
- h -= 1;
- }
- PBM_END
- pbm_freerow(pixelrow);
- return rv;
- }
-
- static char doc_write[] = "Write (string) data to the PBM file";
-
- static PyObject *
- pbm_write(self, args)
- pbmobject *self;
- PyObject *args;
- {
- unsigned char *data;
- int datalen;
- int i, w, h, rowlen;
- PyObject *fmt;
- bit *pixelrow;
- int forceplain;
- FILE *filep;
-
- if (!PyArg_ParseTuple(args, "s#", &data, &datalen))
- return NULL;
- if (self->is_reader) {
- PyErr_SetString(errobject, "Cannot write() to reader object");
- return NULL;
- }
- /* XXXX Get args from self->dict and write the data */
- if ( !pbmselfattr(self, "width", "i", &w, 1) ||
- !pbmselfattr(self, "height", "i", &h, 1) ||
- !pbmselfattr(self, "format", "O", &fmt, 1) )
- return NULL;
-
- forceplain = 0;
- pbmselfattr(self, "forceplain", "i", &forceplain, 0);
-
- rowlen = w;
-
- if ( fmt != format_pbm ) {
- PyErr_SetString(errobject, "Unsupported image format");
- return NULL;
- }
-
- if( rowlen*h != datalen ) {
- PyErr_SetString(errobject, "Incorrect datasize");
- return NULL;
- }
-
- if ((filep = fopen(self->filename, forceplain?"w":"wb")) == NULL) {
- PyErr_SetFromErrno(PyExc_IOError);
- return 0;
- }
- #ifdef macintosh
- setfiletype(self->filename, '????', 'PPBM');
- #endif
-
- pixelrow = 0;
- PBM_START
- if ( pixelrow )
- pbm_freerow(pixelrow);
- fclose(filep);
- return NULL;
- PBM_ENDSTART
-
- pixelrow=pbm_allocrow(w);
-
- pbm_writepbminit(filep, w, h, forceplain);
- while( h > 0 ) {
- for(i=0; i<w; i++)
- pixelrow[i] = data[i];
- pbm_writepbmrow(filep, pixelrow, w, forceplain);
- data += rowlen;
- h -= 1;
- }
- PBM_END
- pbm_freerow(pixelrow);
- if (fclose(filep) != 0) {
- PyErr_SetFromErrno(PyExc_IOError);
- return NULL;
- }
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- static struct PyMethodDef pbm_methods[] = {
- {"read", (PyCFunction)pbm_read, 1, doc_read},
- {"write", (PyCFunction)pbm_write, 1, doc_write},
- {NULL, NULL} /* sentinel */
- };
-
- static PyObject *
- pbm_getattr(xp, name)
- pbmobject *xp;
- char *name;
- {
- PyObject *v;
-
- if (xp->dict != NULL) {
- if ( strcmp(name, "__dict__") == 0 ) {
- Py_INCREF(xp->dict);
- return xp->dict;
- }
- if ( strcmp(name, "__doc__") == 0 ) {
- return PyString_FromString(doc_pbm);
- }
- v = PyDict_GetItemString(xp->dict, name);
- if (v != NULL) {
- Py_INCREF(v);
- return v;
- }
- }
- return Py_FindMethod(pbm_methods, (PyObject *)xp, name);
- }
-
- static int
- pbm_setattr(xp, name, v)
- pbmobject *xp;
- char *name;
- PyObject *v;
- {
- if (xp->dict == NULL) {
- xp->dict = PyDict_New();
- if (xp->dict == NULL)
- return -1;
- }
- if (v == NULL) {
- int rv = PyDict_DelItemString(xp->dict, name);
- if (rv < 0)
- PyErr_SetString(PyExc_AttributeError,
- "delete non-existing imgpbm attribute");
- return rv;
- }
- else
- return PyDict_SetItemString(xp->dict, name, v);
- }
-
- static PyTypeObject Pbmtype = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /*ob_size*/
- "imgpbm", /*tp_name*/
- sizeof(pbmobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)pbm_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc)pbm_getattr, /*tp_getattr*/
- (setattrfunc)pbm_setattr, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- };
-
- static char doc_newreader[] =
- "Return an object that reads the PBM/PBM file passed as argument";
-
- static PyObject *
- pbm_newreader(self, args)
- PyObject *self;
- PyObject *args;
- {
- char *filename;
- pbmobject *obj;
-
- if (!PyArg_ParseTuple(args, "s", &filename))
- return NULL;
- if ((obj = newpbmobject()) == NULL)
- return NULL;
- if ( !initpbmreader(obj, filename) ) {
- pbm_dealloc(obj);
- return NULL;
- }
- return (PyObject *)obj;
- }
-
- static char doc_newwriter[] =
- "Return an object that writes the PBM file passed as argument";
-
- static PyObject *
- pbm_newwriter(self, args)
- PyObject *self;
- PyObject *args;
- {
- char *filename;
- pbmobject *obj;
-
- if (!PyArg_ParseTuple(args, "s", &filename))
- return NULL;
- if ((obj = newpbmobject()) == NULL)
- return NULL;
- if ( !initpbmwriter(obj, filename) ) {
- pbm_dealloc(obj);
- return NULL;
- }
- return (PyObject *)obj;
- }
-
-
- /* List of functions defined in the module */
-
- static struct PyMethodDef pbm_module_methods[] = {
- {"reader", pbm_newreader, 1, doc_newreader},
- {"writer", pbm_newwriter, 1, doc_newwriter},
- {NULL, NULL} /* sentinel */
- };
-
-
- /* Initialization function for the module (*must* be called initimgpbm) */
- static char doc_imgpbm[] =
- "Module that reads images from PBM files writes them too.";
-
-
- void
- initimgpbm()
- {
- PyObject *m, *d, *x, *formatmodule, *formatdict;
-
- /* Create the module and add the functions */
- m = Py_InitModule("imgpbm", pbm_module_methods);
-
- /* Add some symbolic constants to the module */
- d = PyModule_GetDict(m);
- errobject = PyString_FromString("imgpbm.error");
- PyDict_SetItemString(d, "error", errobject);
- x = PyString_FromString(doc_imgpbm);
- PyDict_SetItemString(d, "__doc__", x);
-
- /* Get supported formats */
- if ((formatmodule = PyImport_ImportModule("imgformat")) == NULL)
- Py_FatalError("imgpbm depends on imgformat");
- if ((formatdict = PyModule_GetDict(formatmodule)) == NULL)
- Py_FatalError("imgformat has no dict");
-
- format_pbm = PyDict_GetItemString(formatdict,"pbmbitmap");
- format_choices = Py_BuildValue("(O)", format_pbm);
-
- /* Initialize pbmplus */
- {
- int pbm_argc;
- static char *pbm_arglist[] = { "pbmplus", 0};
- char **pbm_argv;
-
- pbm_argc = 1;
- pbm_argv = pbm_arglist;
- PBM_START /* { */
- Py_FatalError("pbmplus initialization error");
- } /* PBM_ENDSTART won't work here, it has return NULL */
- pbm_init(&pbm_argc, pbm_argv);
- PBM_END
- }
-
- /* Check for errors */
- if (PyErr_Occurred())
- Py_FatalError("can't initialize module imgpbm");
- }
-